package com.tuo51.evaluate.service.impl;


import com.tuo51.evaluate.domain.news.Article;
import com.tuo51.evaluate.domain.news.ArticleCategory;
import com.tuo51.evaluate.domain.news.ArticleListItem;
import com.tuo51.evaluate.domain.tags.RelObjectTag;
import com.tuo51.evaluate.repositories.article.ArticleCategoryRepository;
import com.tuo51.evaluate.repositories.article.ArticleListItemRepository;
import com.tuo51.evaluate.repositories.article.ArticleRepository;
import com.tuo51.evaluate.repositories.tags.RelObjectTagRepository;
import com.tuo51.evaluate.service.article.ArticleService;
import com.tuo51.evaluate.vo.news.ArticleListItemVO;
import com.tuo51.evaluate.vo.news.ArticleVO;
import com.tuo51.foudation.exception.BusinessException;
import com.tuo51.foudation.model.ErrorCode;
import com.tuo51.foudation.query.base.PagerQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.util.List;
import java.util.stream.Collectors;

import static com.tuo51.foudation.constant.APPConstants.TagRelObjectType.NEWSITEM;

/**
 * *******************************
 * Created by Ron.
 * form com.tuo51
 * on 2017/7/26
 * *******************************
 */
@Service
@Transactional
//@CacheConfig(cacheNames = "ArticleServiceImpl")
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private ArticleListItemRepository newsItemRepository;

    @Autowired
    private ArticleCategoryRepository categoryRepository;

    @Autowired
    private RelObjectTagRepository relObjectTagRepository;

    @Override
//    @Cacheable(keyGenerator = "keyGenerator")
    public Page<ArticleListItem> homePageNews(boolean vip, String channel, PagerQuery pagerQuery){
        return newsList(vip, channel, null, null, null, pagerQuery);
    }

    @Override
    public Page<ArticleListItem> newsList(boolean vip, String channel, String category, String staticCode,  String keyword, PagerQuery pagerQuery) {
        return newsList(vip, channel, null, category, staticCode, keyword, pagerQuery);
    }

    @Override
    public Page<ArticleListItem> newsList(boolean vip, String channel, String categoryId, String category, String staticCode, String keyword, PagerQuery pagerQuery){

        PageRequest pager = PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize());

        if (StringUtils.isNotEmpty(staticCode)) {
            ArticleCategory c = categoryRepository.findByStaticCodeAndDeletedIsFalse(staticCode);
            if (c != null){
                category = c.getTitle();
            }else{
                category = staticCode;
            }
        }

        final String categoryName = category;
        final String cid = categoryId;
        Page<ArticleListItem> ret = newsItemRepository.findAll(new Specification<ArticleListItem>() {
            @Override
            public Predicate toPredicate(Root<ArticleListItem> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                Predicate base = cb.isNotNull(root.get("id"));

                if (!vip){
                    Predicate p = cb.isFalse(root.get("vip"));
                    base = cb.and(base, p);
                }

                if (StringUtils.isNotEmpty(categoryName)){
                    String key = "%" + categoryName + "%";
                    Predicate p = cb.like(root.get("categories"), key);
                    base = cb.and(base, p);
                }else if (StringUtils.isNotEmpty(cid)){
                    Predicate p = cb.equal(root.get("categoryId"), cid);
                    base = cb.and(base, p);
                }
                if (StringUtils.isNotEmpty(keyword)){
                    String key = "%" + keyword + "%";
                    Predicate p = cb.or(cb.like(root.get("title"), key),
                            cb.like(root.get("subTitle"), key),
                            cb.like(root.get("tags"), key),
                            cb.like(root.get("extFlag"), key),
                            cb.like(root.get("channel"), key));
                    base = cb.and(base, p);
                }

                if ("__ALL__".equals(channel)){

                }else
                if (StringUtils.isNotEmpty(channel)){
                    Predicate p = cb.equal(root.get("channel"), channel);
                    base = cb.and(base, p);
                }else{
                    Predicate p = cb.isNull(root.get("channel"));
                    base = cb.and(base, p);
                }


                base = cb.and(base, cb.isFalse(root.get("deleted")));

                query.where(base);

                query.orderBy(cb.desc(root.get("orderWeight")), cb.desc(root.get("created")));

                return query.getRestriction();
            }
        }, pager);

        return ret;
    }

    @Override
    public List<ArticleListItem> getArticleItemsByObject(List<String> objectIds, Integer objectType, Integer month) {

        List<RelObjectTag> rels = relObjectTagRepository.findAllBySourceObjectIdsAndType(objectIds, objectType, NEWSITEM.getValue());

        List<String> itemIds = rels.stream().filter(o -> StringUtils.isNotEmpty(o.getObjId())).map(o -> {
            return o.getObjId();
        }).collect(Collectors.toList());

        List<ArticleListItem> ret = newsItemRepository.findAllByIdIn(itemIds);

        return ret;
    }

    @Override
    public boolean deleteItem(String itemId) {

        if (StringUtils.isEmpty(itemId)){
            throw new BusinessException(ErrorCode.PARAM_NOT_BLANK, "参数错误");
        }

        ArticleListItem item = newsItemRepository.getOne(itemId);
        if (item == null){
            throw new BusinessException(ErrorCode.MATERIAL_NOT_EXIST, "对象不存在");
        }

        newsItemRepository.delete(item);

        return true;
    }

    @Override
    public boolean deleteArticle(String articleId) {

        if (StringUtils.isEmpty(articleId)){
            throw new BusinessException(ErrorCode.PARAM_NOT_BLANK, "参数错误");
        }

        Article item = articleRepository.getOne(articleId);
        if (item == null){
            throw new BusinessException(ErrorCode.MATERIAL_NOT_EXIST, "对象不存在");
        }

        articleRepository.delete(item);

        return true;
    }

    @Override
    public Article articleDetail(String articleId) {
        Article ret = articleRepository.getOne(articleId);

        if(ret == null){
            throw new BusinessException(ErrorCode.MATERIAL_NOT_EXIST, "文章不存在");
        }

        return ret;
    }

    @Override
    public Page<Article> articleList(String keyword, PagerQuery pagerQuery){

        PageRequest pager = PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize());

        Page<Article> ret = articleRepository.findAll(new Specification<Article>() {
            @Override
            public Predicate toPredicate(Root<Article> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                Predicate base = cb.isNotNull(root.get("id"));

                if (StringUtils.isNotEmpty(keyword)){
                    String key = "%" + keyword + "%";
                    Predicate p = cb.or(
                            cb.like(root.get("articletitle"), key),
                            cb.like(root.get("articleauthor"), key),
                            cb.like(root.get("synopsis"), key),
                            cb.like(root.get("content"), key));
                    base = cb.and(base, p);
                }


                base = cb.and(base, cb.isFalse(root.get("deleted")));

                query.where(base);

                query.orderBy(cb.desc(root.get("created")));

                return query.getRestriction();
            }
        },pager);

        return ret;
    }

    @Override
    public ArticleListItem editItem(ArticleListItemVO item){
        ArticleListItem ret = null;
        if (StringUtils.isNotEmpty(item.getId())){
            ret = newsItemRepository.getOne(item.getId());
            if (ret == null){
                throw new BusinessException(ErrorCode.MATERIAL_NOT_EXIST, "条目不存在");
            }
        }else{
            ret = new ArticleListItem();
        }

        ret.setTitle(item.getTitle());
        ret.setSubTitle(item.getSubTitle());
        ret.setExtFlag(item.getExtFlag());
        ret.setCategories(item.getCategories());
        ret.setChannel(item.getChannel());
        ret.setCoverURL(item.getCoverURL());
        ret.setTags(item.getTags());
        ret.setLinkURL(item.getLinkURL());
        ret.setVip(item.getVip());
        ret.setOrderWeight(item.getOrderWeight());

        newsItemRepository.save(ret);

        return ret;
    }

    @Override
    public Article editArticle(ArticleVO article){
        Article ret = null;
        if (StringUtils.isNotEmpty(article.getId())){
            ret = articleRepository.getOne(article.getId());
            if (ret == null){
                throw new BusinessException(ErrorCode.MATERIAL_NOT_EXIST, "条目不存在");
            }
        }else{
            ret = new Article();
        }

        ret.setContent(article.getContent());
        ret.setTitle(article.getTitle());
        ret.setAuthor(article.getAuthor());
        ret.setKeyword(article.getKeyword());

        articleRepository.save(ret);

        return ret;
    }
}
